//监控
var Watcher = function (el, vm, value, type) {

    this.el = el;
    this.vm = vm;
    this.value = value;
    this.type = type;
    this.update();

}

Watcher.prototype = {
    update: function () {
        this.el[this.type] = this.vm[this.value];
    }
}

var myVue = function (options) {
    'use strict';

    //源码学习
    console.log('vue源码学习');
    this.$el = document.querySelector(options.el);
    //数据
    this.data = options.data;
    // 需要监听的任务列表
    this.watcherTask = {};

    //方法
    this.methods = options.methods;

    this.constructor = function () {
        this.observer(options.data);
        this.compile(this.$el);
    }

    //监控数据变化
    this.proxyData = function (key) {
        let that = this;
        if (Object.prototype.toString.call(this.data[key]) === '[object Array]') {
            this.data[key] = new Proxy(this.data[key], {
                get(obj, prop) {
                    return obj[prop];
                },
                set(obj, prop, newvalue) {
                    obj[prop] = newvalue;
                    return true;
                }
            });
        } else {
            Object.defineProperty(that, key, {
                configurable: false,
                enumerable: true,
                get() {
                    return that.data[key];
                },
                set(newVal) {
                    that.data[key] = newVal;
                }
            });
        }
    }

    //监听
    Object.keys(this.data).forEach((key) => {
        this.proxyData(key);
    });

    //观察数据变化
    this.observer = function (data) {
        let that = this;
        Object.keys(data).forEach(key => {
            let value = data[key];
            this.watcherTask[key] = [];

            //判断是否是数组
            if (Object.prototype.toString.call(data[key]) === '[object Array]') {
                data[key] = new Proxy(data[key], {
                    get(obj, prop) {
                        return obj[prop];
                    },
                    set(obj, prop, newvalue) {
                        console.log('数组更新了',  obj);
                        obj[prop] = newvalue;
                        that.watcherTask[key][0].list.forEach(item => {
                            console.log(item)
                            //task.update();
                        })
                        return true;
                    }
                })
            } else {
                Object.defineProperty(data, key, {
                    configurable: false,
                    enumerable: true,
                    get() {
                        return value;
                    },
                    set(newValue) {
                        if (newValue != value) {
                            value = newValue;
                            console.log('你更新了数据', that.watcherTask[key]);
                            that.watcherTask[key].forEach(task => {
                                task.update();
                            })
                        }
                    }
                });
            }
        });
    };

    //解析DOM
    this.compile = function (el, itemData) {
        const nodes = el.childNodes;
        const that = this;
        for (let i = 0; i < nodes.length; i++) {
            const node = nodes[i];
            if (node.nodeType === 3) {
                let text = node.textContent.trim();
                if (!text) continue;

                this.compileText(node, itemData ? itemData : that.data, 'textContent');
            } else if (node.nodeType === 1) {

                //如果是循环的话
                if (node.hasAttribute('v-for')) {
                    let attrVal = node.getAttribute('v-for');
                    node.removeAttribute('v-for');
                    let reg = /\s+in\s+/g;
                    //获取分割的字符串
                    let split_str = reg.exec(attrVal);
                    //获取分割的位置
                    let index = attrVal.search(reg);
                    var str_item = attrVal.substring(0, index);
                    var str_data = attrVal.substring(index + split_str[0].length, attrVal.length);
                    const parent = node.parentNode;
                    let obj = { parentNode: parent, list: [] }

                    for (let i = 0; i < that.data[str_data].length; i++) {
                        let new_nodes = node.cloneNode(true);
                        parent.insertBefore(new_nodes, node);
                        this.compile(new_nodes, that.data[str_data][i]);
                        // let obj = new Watcher(new_nodes, that.data, str_data, 'innerHTML');
                        let item = { nodes: new_nodes, index: i, show: true }
                        obj.list.push(item);
                    }
                    this.watcherTask[str_data].push(obj);
                    parent.removeChild(node);


                } else {

                    if (node.childNodes.length > 0) {
                        this.compile(node, itemData ? itemData : that.data);
                    }

                    if (node.hasAttribute('v-model') && (node.tagName === 'INPUT' || node.tagName === 'TEXTAREA')) {
                        node.addEventListener('input', (() => {
                            let attrVal = node.getAttribute('v-model');
                            let obj = new Watcher(node, that.data, attrVal, 'value');
                            this.watcherTask[attrVal].push(obj);
                            node.removeAttribute('v-model');
                            return () => {
                                that.data[attrVal] = node.value
                            }
                        })())
                    }

                    //普通绑定
                    if (node.hasAttribute('v-html')) {
                        let attrVal = node.getAttribute('v-html');
                        let obj = new Watcher(node, that.data, attrVal, 'innerHTML');
                        this.watcherTask[attrVal].push(obj);
                        node.removeAttribute('v-html');
                    }

                    //点击事件绑定
                    if (node.hasAttribute('@click')) {
                        let attrVal = node.getAttribute('@click');
                        node.removeAttribute('@click');
                        node.addEventListener('click', e => {
                            this.methods[attrVal] && this.methods[attrVal].bind(that.data)();
                        });
                    }
                }
            }
        }
    }

    //解析DOM动态数据
    this.compileText = function (node, data, type) {
        let reg = /\{\{(.*?)\}\}/g, txt = node.textContent;

        if (reg.test(txt)) {
            node.textContent = txt.replace(reg, (matched, value) => {
                value = value.trim();
                let tpl = this.watcherTask[value] || []
                let obj = new Watcher(node, this, value, type);
                tpl.push(obj);
                if (value.split('.').length > 1) {
                    let v = null
                    value.split('.').forEach((val, i) => {
                        v = !v ? data[val] : v[val]
                    })
                    return v
                } else {
                    return data[value]
                }
            })
        }
    }

    //创建
    const createApp = ((arg) => {
        const app = {
            mount: () => { }
        };

        observer(arg.data);

        return app;

    })

    this.constructor();

};


